package org.example.day10;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 4.1.6: 使用多个Condition实现通知部分线程 正确用法
 *      ①同一把锁可以new多个Condition,如conditionA、conditionB
 *      ②线程A获取锁后可以通过conditionA进行await,从而达到唤醒的时候可以通过conditionA.signalAll()仅唤醒A
 */
public class MyThread11 {
    private Lock lock = new ReentrantLock();
    public Condition conditionA = lock.newCondition();
    public Condition conditionB = lock.newCondition();
    public void awaitA(){
        try {
            lock.lock();
            System.out.println("awaitA begin time = " + System.currentTimeMillis() + " Threadname = " + Thread.currentThread().getName());
            conditionA.await();
            System.out.println("awaitA end time = " + System.currentTimeMillis() + " Threadname = " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void awaitB(){
        try {
            lock.lock();
            System.out.println("awaitB begin time = " + System.currentTimeMillis() + " Threadname = " + Thread.currentThread().getName());
            conditionB.await();
            System.out.println("awaitB end time = " + System.currentTimeMillis() + " Threadname = " + Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
    public void signal_A(){
        try {
            lock.lock();
            System.out.println("signal_A 时间为: " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
            //通过不同的condition达到指定唤醒.
            conditionA.signalAll();
        } finally {
            lock.unlock();
        }
    }
    public void signal_B(){
        try {
            lock.lock();
            System.out.println("signal_B 时间为: " + System.currentTimeMillis() + " ThreadName = " + Thread.currentThread().getName());
            conditionB.signalAll();
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyThread11 m11 = new MyThread11();
        Thread11A ta = new Thread11A(m11);
        ta.setName("A");
        ta.start();
        Thread11B tb = new Thread11B(m11);
        tb.setName("B");
        tb.start();
        Thread.sleep(3000);
        m11.signal_A();
    }
}

class Thread11A extends Thread{
    private MyThread11 m11;

    public Thread11A(MyThread11 m11) {
        this.m11 = m11;
    }

    @Override
    public void run() {
        m11.awaitA();
    }
}

class Thread11B extends Thread{
    private MyThread11 m11;

    public Thread11B(MyThread11 m11) {
        this.m11 = m11;
    }

    @Override
    public void run() {
        m11.awaitB();
    }
}
